package aliyun

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net"

	"github.com/sirupsen/logrus"

	"gitee.com/bjf-fhe/apicat/entry"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/ec2"
	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
)

type Handler struct {
	client  *ec2.Client
	ncfg    *aws.Config
	existed map[string]*entry.LogEntry
	dest    string
	ctx     context.Context
}

func createClient(ncfg *aws.Config) (_result *ec2.Client, _err error) {

	// 访问的域名
	_result = ec2.NewFromConfig(*ncfg)
	return _result, nil
}

func (h *Handler) Init(ncfg *aws.Config, ctx context.Context, dest string) (err error) {

	h.ctx = ctx
	h.client, err = createClient(ncfg)

	if err != nil {
		return
	}

	h.ncfg = ncfg
	h.dest = dest

	h.existed = make(map[string]*entry.LogEntry)

	if h.dest != "" {
		err := h.fetchAcls(h.dest)
		if err != nil {
			return err
		}
	} else {
		return errors.New("Aws Dest（AWS配置拦截规则ID）没有设置，请使用--aws-dest配置该参数")
	}

	return err
}

func (h *Handler) fetchAcls(aclId string) (err error) {

	var result *ec2.DescribeSecurityGroupRulesOutput
	result, err = h.client.DescribeSecurityGroupRules(h.ctx, &ec2.DescribeSecurityGroupRulesInput{
		Filters: []types.Filter{
			{
				Name: aws.String("group-id"),
				Values: []string{
					h.dest,
				},
			},
		},
	})

	if err == nil && result.SecurityGroupRules != nil {
		for _, inServer := range result.SecurityGroupRules {
			if inServer.CidrIpv4 != nil {
				fmt.Println(*inServer.CidrIpv4, *inServer.SecurityGroupRuleId, *inServer.IsEgress, *inServer.FromPort, *inServer.ToPort)
			} else {
				fmt.Println(*inServer.CidrIpv6, *inServer.SecurityGroupRuleId, *inServer.IsEgress, *inServer.FromPort, *inServer.ToPort)
			}
			var logEntry entry.LogEntry
			if inServer.Description != nil && !(*inServer.IsEgress) {
				err := json.Unmarshal([]byte(*inServer.Description), &logEntry)
				if err == nil {
					if *inServer.IpProtocol == "4" {
						h.existed[*inServer.CidrIpv4] = &logEntry
					} else {
						h.existed[*inServer.CidrIpv6] = &logEntry
					}
				}
			}

		}
	}
	return err
}

type AclEntrys []AclEntry

type AclEntry struct {
	Entry   string `json:"entry"`
	Comment string `json:"comment"`
}

func (h *Handler) NotifyAdd(toAdd *entry.LogEntry) error {
	if _, existed := h.existed[toAdd.Client]; existed {
		logrus.Info(toAdd.Client, "已经存在")
		return nil
	}

	ip := net.ParseIP(toAdd.Client)

	var input ec2.AuthorizeSecurityGroupIngressInput
	var permission = types.IpPermission{
		IpProtocol: aws.String("tcp"),
		FromPort:   aws.Int32(0),
		ToPort:     aws.Int32(0),
	}
	if ip.To4() != nil {
		permission.IpRanges = []types.IpRange{
			{
				CidrIp:      aws.String(toAdd.Client + "/32"),
				Description: aws.String(toAdd.Description()),
			},
		}
	} else {
		permission.Ipv6Ranges = []types.Ipv6Range{
			{
				CidrIpv6:    aws.String(toAdd.Client + "/128"),
				Description: aws.String(toAdd.Description()),
			},
		}
	}
	input.IpPermissions = []types.IpPermission{permission}
	input.GroupId = &h.dest

	// fmt.Println(entrys)
	// entrys = `[{"entry":"10.0.1.1","comment":"privaterule1"},{"entry":"192.168.1.1","comment":"privaterule2"}]`

	_, err := h.client.AuthorizeSecurityGroupIngress(h.ctx, &input)

	// if te, ok := err.(*tea.SDKError); ok && *te.Code == "InvalidParam.AclEntryExists" {
	// 	return nil
	// }

	return err
}

func (h *Handler) NotifyDel(toAdd ...*entry.LogEntry) error {
	logrus.Fatal("TODO Del")
	return nil
}

func (h *Handler) ListExistedEntrys() (map[string]*entry.LogEntry, error) {
	return h.existed, nil
}
